Skip to content

test(cuda_core): capture machine state on the first CUDA OOM - #2458

Merged
juenglin merged 2 commits into
NVIDIA:mainfrom
juenglin:oom-diagnostics
Aug 20, 2026
Merged

test(cuda_core): capture machine state on the first CUDA OOM#2458
juenglin merged 2 commits into
NVIDIA:mainfrom
juenglin:oom-diagnostics

Conversation

@juenglin

@juenglin juenglin commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Issue #2381 reported intermittent runs where ~190 tests failed with
CUDA_ERROR_OUT_OF_MEMORY. That issue is now closed: the root cause was
two driver-managed memory pools (the default device pool and the CUDA graph
pool) that each permanently reserve host virtual-address space sized at
roughly 2x installed device memory, combined with Windows ASLR randomizing
whether two such reservations can find contiguous room. Turning ASLR off on
the affected machine made the suite pass deterministically; see the issue
for the full investigation.

That investigation surfaced a lesson this PR is now built around:
CUDA_ERROR_OUT_OF_MEMORY does not mean the device is out of memory. The
driver returns it whenever it cannot obtain some resource, and creating --
or even just looking up -- a memory pool reserves host virtual address space
before touching any device memory. A pytest log alone cannot distinguish
"host VA exhausted" from "device physical memory exhausted" from "another
process is holding the GPU," and reproducing the original failure required a
specific driver model, so any evidence has to come from whoever hits it next.

This PR keeps that as its purpose: a failure-triggered OOM reason checker
for the next time this error shows up, anywhere, for any reason -- not a
re-diagnosis of #2381, which is already resolved.

What changed since the original version of this PR

  • Dropped nvidia-smi. The original version shelled out to
    nvidia-smi -q and --query-compute-apps. Per review, this now uses only
    cuda.bindings.driver APIs -- no subprocess, no NVML.
  • Replaced the raw dump with a classifier. Instead of printing driver
    call results and leaving the reader to interpret them, helpers/oom_diagnostics.py
    now runs an ordered sequence of probes into a ProbeSnapshot and turns it
    into a one-line verdict via a pure classify() function:
    physical device memory exhaustion, host VA exhaustion (at a small or a
    pool-sized granularity), default-mempool materialization failure, or
    inconclusive.
  • Portable by construction. Every probe is a documented driver call
    against the current context/device; there are no OS-specific branches.
    Devices without mempools or VMM skip those steps rather than failing.
    Alignment comes from cuMemGetAllocationGranularity (falling back to 2 MiB)
    rather than a hardcoded page size.
  • Kept the pytest harness (latch to the first OOM, artifact file via
    terminalreporter, pytest_terminal_summary pointer) essentially
    unchanged; that part of the design was already reviewed favorably.
  • Kept tests
    They cover the harness and the classify() decision table with injected
    snapshots (no GPU needed) plus one live smoke test that only exercises the
    side-effect-free prefix (context, cuMemGetInfo, attributes) -- it never
    calls cuDeviceGetMemPool or creates a pool, so running the test suite
    doesn't itself materialize the ~2x-device-memory reservation this checker
    is trying to diagnose.

Checklist

  • New or existing tests cover these changes.
  • The documentation is up to date with these changes.

@copy-pr-bot

copy-pr-bot Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually.

Contributors can view more details about this message here.

@github-actions github-actions Bot added the cuda.core Everything related to the cuda.core module label Jul 30, 2026
@juenglin juenglin self-assigned this Jul 30, 2026
@juenglin juenglin added P0 High priority - Must do! bug Something isn't working experiment Describes an investigation or measurement labels Jul 30, 2026
@juenglin juenglin added this to the cuda.core 1.2.0 milestone Jul 30, 2026
@juenglin

Copy link
Copy Markdown
Contributor Author

/ok to test

@github-actions

This comment has been minimized.

@juenglin
juenglin marked this pull request as ready for review July 30, 2026 22:59
Comment thread cuda_core/tests/helpers/oom_diagnostics.py Outdated
Comment thread cuda_core/tests/test_helpers.py

@lijinf2 lijinf2 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR leverages pytest_runtest_makereport and pytest_terminal_summary to collect runtime specs of the first error in a sequence of errors of the same type. Good idea!

@juenglin
juenglin marked this pull request as draft July 31, 2026 18:28
@juenglin

Copy link
Copy Markdown
Contributor Author

/ok to test 3ccde3d

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Example terminal output:

==============================================================================
cuda_core OOM reason checker: first CUDA_ERROR_OUT_OF_MEMORY of this session
==============================================================================
test:      tests/test_memory.py::test_device_memory_resource_default_pool
phase:     call
pid:       17012
platform:  win32
exception: CUDA_ERROR_OUT_OF_MEMORY: The API call failed because it was unable to allocate enough memory or other resources to perform the requested operation.

CUDA_ERROR_OUT_OF_MEMORY means the driver could not obtain some resource;
it is not proof that device memory is exhausted. Creating -- or even just
looking up -- a memory pool first reserves a host virtual-address window
(observed default: about 2x installed device memory) before any device
memory is touched. That reservation can fail while cuMemGetInfo still
reports most of the device free. The probes below check host VA and
physical device memory separately so the two are not confused. Note that
the '2x device memory' figure is an observation from measurement and a
driver source comment, not a documented guarantee -- it can differ across
driver versions and platforms.

--- direct driver probe (bypasses cuda.core's error reporting) ---
cuCtxGetCurrent() -> ok
cuMemGetInfo() -> free=143.50 GiB, total=178.81 GiB (80.3% free)
mempools supported: True
VMM (cuMemAddressReserve) supported: True
small cuMemAlloc(4 KiB) -> ok, freed
allocation granularity: 2097152 bytes
cuMemAddressReserve(2097152 bytes) -> ok, freed
cuMemAddressReserve(384309411840 bytes, observed default pool window, not a documented guarantee) -> <failed: CUresult.CUDA_ERROR_OUT_OF_MEMORY>
cuDeviceGetMemPool(dev 0) -> <failed: CUresult.CUDA_ERROR_OUT_OF_MEMORY>
cuDeviceGetDefaultMemPool(dev 0) -> <failed: CUresult.CUDA_ERROR_OUT_OF_MEMORY>
cuMemPoolCreate(maxSize=2097152) -> ok, destroyed

verdict: likely host VA exhaustion for the pool-sized window only: a capped memory pool (helpers.constants.POOL_SIZE) still creates fine, but a reservation the size of the observed default pool window does not
==============================================================================
(diagnostics also written to /path/to/cuda_core/cuda_core_oom_diagnostics.txt)

@juenglin
juenglin marked this pull request as ready for review August 20, 2026 00:00
@juenglin
juenglin merged commit cbc338d into NVIDIA:main Aug 20, 2026
211 of 213 checks passed
@github-actions

Copy link
Copy Markdown
Doc Preview CI
Preview removed because the pull request was closed or merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working cuda.core Everything related to the cuda.core module experiment Describes an investigation or measurement P0 High priority - Must do!

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants